﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;

namespace SilverlightApplication
{
	public partial class MagnifierControl : UserControl
    {
        bool clicking = false;

        DispatcherTimer dt;
       
        double time;

        Point distancetoGlassCenter;

        #region Dependency Properties

        public static readonly DependencyProperty XProperty;
        public static readonly DependencyProperty YProperty;
        public static readonly DependencyProperty AngleProperty;

        #endregion

        #region Properties

        public double X
        {
            get { return (double)GetValue(XProperty); }
            set { SetValue(XProperty, value); }
        }

        public double Y
        {
            get { return (double)GetValue(YProperty); }
            set { SetValue(YProperty, value); }
        }

        public double Angle
        {
            get { return (double)GetValue(AngleProperty); }
            set { SetValue(AngleProperty, value); }
        }

        #endregion

        #region Constructors

        static MagnifierControl()
        {
            XProperty = DependencyProperty.Register("X",
                                                    typeof(double),
                                                    typeof(MagnifierControl),
                                                    new PropertyMetadata(OnXChanged));

            YProperty = DependencyProperty.Register("Y",
                                                    typeof(double),
                                                    typeof(MagnifierControl),
                                                    new PropertyMetadata(OnYChanged));

            AngleProperty = DependencyProperty.Register("Angle",
                                                    typeof(double),
                                                    typeof(MagnifierControl),
                                                    new PropertyMetadata(OnAngleChanged));
        }

        public MagnifierControl()
		{
			// Required to initialize variables
			InitializeComponent();
            Loaded += new RoutedEventHandler(MagnifierControl_Loaded);
        }

        #endregion

        #region Implementation

        private static void OnXChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            MagnifierControl p = (MagnifierControl)obj;
            p.MoveXMagnifyingGlass(p.X);
        }

        private static void OnYChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            MagnifierControl p = (MagnifierControl)obj;
            p.MoveYMagnifyingGlass(p.Y);
        }

        private static void OnAngleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            MagnifierControl p = (MagnifierControl)obj;
            p.glassRT.Angle = p.Angle;
        }

        void MagnifierControl_Loaded(object sender, RoutedEventArgs e)
        {
            // Parent control needs to be a panel!
            Panel parent = (Panel)this.Parent;
            rctBackground.Fill = parent.Background;

            // Start the timer for the animation
            dt = new System.Windows.Threading.DispatcherTimer();
            dt.Interval = new TimeSpan(0, 0, 0, 0, 10);
            dt.Tick += new EventHandler(dt_Tick);
            dt.Start();

            stbGlassGoBack.Completed += delegate
            {
                dt.Start();
            };

           
            time = 0;
        }

        private void Magnifier_MouseMove(object sender, MouseEventArgs e)
        {
            if (clicking)
            {
                Point p = e.GetPosition(Magnifier);

                X = p.X + distancetoGlassCenter.X;
                Y = p.Y + distancetoGlassCenter.Y;
            }
        }

        void MoveXMagnifyingGlass(double x)
        {
            Point ellipseCenter = new Point(x, glass.Center.Y);
            glass.Center = ellipseCenter;

            scaleTransform.CenterX = x;
            glassTT.X = x;
        }

        void MoveYMagnifyingGlass(double y)
        {
            Point ellipseCenter = new Point(glass.Center.X, y);
            glass.Center = ellipseCenter;

            scaleTransform.CenterY = y;
            glassTT.Y = y;
        }


        void MoveMagnifyingGlass(double x, double y)
        {
            MoveXMagnifyingGlass(x);
            MoveYMagnifyingGlass(y);
        }

        #endregion

        private void MouseUp(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement fe = sender as FrameworkElement;
            fe.ReleaseMouseCapture();

            clicking = false;

            Random rand = new Random();
            time = rand.Next(int.MaxValue) * Math.PI * 2 / int.MaxValue;
            Position pos = calculatePosition(time);

            DAXAnimation.From = X;
            DAYAnimation.From = Y;
            DAAngleAnimation.From = Angle;

            DAXAnimation.To = pos.x;
            DAYAnimation.To = pos.y;
            DAAngleAnimation.To = pos.angle;

            stbGlassGoBack.Begin();
        }

        private void MouseDown(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement fe = sender as FrameworkElement;
            fe.CaptureMouse();
            
            clicking = true;
            distancetoGlassCenter.X = glassTT.X - e.GetPosition(Magnifier).X;
            distancetoGlassCenter.Y = glassTT.Y - e.GetPosition(Magnifier).Y;

            dt.Stop();
        }

        void dt_Tick(object sender, EventArgs e)
        {
            if (!clicking)
            {
                Position pos = calculatePosition(time);
                Angle = pos.angle;
                X = pos.x;
                Y = pos.y;
                time += 0.03;
            }
        }

        Position calculatePosition(double time)
        {
            Position pos;
            
            pos.x = Math.Sin(time) * 0.9;
            pos.y = Math.Cos(time * 2 - Math.PI / 2) * 0.2;

            pos.angle = pos.x * 20;

            pos.x = pos.x * Magnifier.ActualWidth / 2 + Magnifier.ActualWidth / 2;
            pos.y = pos.y * Magnifier.ActualHeight / 2 + Magnifier.ActualHeight / 2;

            return pos;
        }

        private void Magnifier_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            // Configure Center Parameters
            glass.Center = new Point(Magnifier.ActualWidth / 2, Magnifier.ActualHeight / 2);
            scaleTransform.CenterX = Magnifier.ActualWidth / 2;
            scaleTransform.CenterY = Magnifier.ActualHeight / 2;
            glassRT_base.CenterX = Magnifier.ActualWidth / 2;
            glassRT_base.CenterY = Magnifier.ActualHeight / 2;
            glassRT.CenterX = Magnifier.ActualWidth / 2;
            glassRT.CenterY = Magnifier.ActualHeight / 2;
            glassTT_base.X = -Magnifier.ActualWidth / 2;
            glassTT_base.Y = -Magnifier.ActualHeight / 2;
        }

        public void Stop()
        {
            dt.Stop();
        }

        public void Play()
        {
            dt.Start();
        }
    }

    public struct Position
    {
        public double x;
        public double y;
        public double angle;
    }
}